package cn.lg.soar.common.util.token;

import cn.lg.soar.common.algorithm.HmacSigner;
import cn.lg.soar.common.algorithm.Signer;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Base64;

/**
 * 自定义的JWT
 * 快速解析校验( 20um )
 * 载体支持任意对象
 * 校验结果信息丰富，不需二次解析
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class SoarJWT implements ISoarJWT {

    public static final String JOIN = ".";
    public static final String SPLIT = "\\.";

    public final static Base64.Encoder ENCODER = Base64.getUrlEncoder();
    public final static Base64.Decoder DECODER = Base64.getUrlDecoder();

    /**
     * 有效时长(ms)
     */
    private final long expire;

    private final Signer signer;

    public SoarJWT(Signer signer, long expire) {
        this.signer = signer;
        this.expire = expire;
    }

    public SoarJWT(Signer signer, Duration expire) {
        this(signer, expire.toMillis());
    }

    public SoarJWT(String secret, long expire) {
        this(HmacSigner.sha256(secret), expire);
    }

    public SoarJWT(String secret, Duration expire) {
        this(secret, expire.toMillis());
    }

    /**
     * 创建token
     * @param payload 载体
     * @param salt 客户端盐
     * @return
     */
    @Override
    public String create(String payload, String salt){
        String expiresTime = String.valueOf(this.expire + System.currentTimeMillis());
        String payloadEn = ENCODER.encodeToString(payload.getBytes(StandardCharsets.UTF_8)).replaceAll("=", "");
        String sign = ENCODER.encodeToString(this.signer.sign(expiresTime + salt + payload)).replaceAll("=", "");
        return sign + JOIN + expiresTime + JOIN + payloadEn;
    }

    /**
     * 创建token
     * @param payload 载体
     * @return
     */
    @Override
    public String create(String payload){
        return create(payload, "");
    }

    /**
     * 校验token
     * @param token
     * @param salt 客户端盐
     * @return
     */
    public String verify(String token, String salt){
        String[] strings = token.split(SPLIT);
        if(strings.length != 3){
            return null;
        }
        long expiresTime = Long.parseLong(strings[1]);
        //验证有效期
        if(expiresTime < System.currentTimeMillis()){
            return null;
        }
        //解析载体
        strings[2] = new String(DECODER.decode(strings[2]), StandardCharsets.UTF_8);
        //验证签名
        String sign = ENCODER.encodeToString(this.signer.sign(strings[1] + salt + strings[2])).replaceAll("=", "");
        if(sign.equals(strings[0])){
            return strings[2];
        }
        return null;
    }


    @Override
    public String getSign(String token) {
        return token.split(SPLIT)[0];
    }

    @Override
    public long getExpire(String token) {
        return Long.parseLong(token.split(SPLIT)[1]);
    }

    @Override
    public String getPayload(String token) {
        return new String(DECODER.decode(token.split(SPLIT)[2]), StandardCharsets.UTF_8);
    }

    /**
     * 解析获取签名
     * @param token
     * @return
     */
    public static String parseSign(String token){
        return token.split(SPLIT)[0];
    }

    /**
     * 解析获取有效期
     * @param token
     * @return
     */
    public static long parseExpiresTime(String token){
        return Long.parseLong(token.split(SPLIT)[1]);
    }

    /**
     * 解析获取载体
     * @param token
     * @return
     */
    public static String parsePayload(String token){
        return new String(DECODER.decode(token.split(SPLIT)[2]), StandardCharsets.UTF_8);
    }

}
